package ifm4j.collections.treeCollections;

import ifm4j.collections.treeCollections.factories.TreeFactory;
import ifm4j.utils.Identifier;

import java.util.Collection;
import java.util.Hashtable;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class TreeNode extends TreeObject implements INonLeaf, INonRoot{
	protected Hashtable<Identifier, INonRoot> children;

    protected INonLeaf parent;

    /**
     * Construct tree node.
     * 
     * @param id
     */
    public TreeNode(Identifier id) {
        super(id);

        parent = null;
        children = new Hashtable<Identifier, INonRoot>();
    }

    @Override
    public final INonLeaf getParent() {
        return this.parent;
    }

    @Override
    public final void setParent(INonLeaf parent) {
        this.parent = parent;
    }

    @Override
    public final Collection<INonRoot> getChildren() {
        return this.children.values();
    }

    @Override
    public INonRoot getChild(Identifier id) {
        return children.get(id);
    }

    /**
     * Add child into node.
     */
    @Override
    public void addChild(INonRoot child) {
        this.children.put(child.getIdentifier(), child);
        child.setParent(this);
    }

    @Override
    public boolean removeChild(INonRoot child) {
        // TODO Auto-generated method stub
        return false;
    }

    /**
     * Contains child
     */
    @Override
    public boolean containChild(INonRoot child) {
        return this.children.contains(child.getIdentifier());
    }

    /**
     * Parse tree node.
     * 
     * @throws TreeCollectionException
     */
    @Override
    public Element toXElem() throws TreeCollectionException {
        Element xelem = super.toXElem();
        for (INonRoot child : this.children.values()) {
            if (!(child instanceof TreeObject)) {
                continue;
            }

            TreeObject obj = (TreeObject) child;
            xelem.appendChild(obj.toXElem());
        }

        return xelem;
    }

    /**
     * Parse XML to tree node.
     * 
     * @param xelem
     * @param treeFactory
     * @param treeNode
     * @throws TreeCollectionException
     */
    public static void xmlParser(Element xelem, TreeFactory treeFactory,
            TreeNode treeNode) throws TreeCollectionException {
        // construct tree root children
        NodeList nodeList = xelem.getChildNodes();
        int len = nodeList.getLength();
        for (int i = 0; i < len; ++i) {
            Node child = nodeList.item(i);
            if (!(child instanceof Element)) {
                continue;
            }

            Element tmpXElem = (Element) child;
            TreeObject tmpObj = TreeObject.xmlParser(tmpXElem, treeFactory);

            if (tmpObj instanceof TreeNode) {
                TreeNode node = (TreeNode) tmpObj;
                TreeNode.xmlParser(tmpXElem, treeFactory, node);
            } else if (tmpObj instanceof TreeLeaf) {
                TreeLeaf leaf = (TreeLeaf) tmpObj;
                TreeLeaf.xmlParser(tmpXElem, treeFactory, leaf);
            }

            treeNode.addChild((INonRoot) tmpObj);
        }
    }

    /**
     * Equals.
     */
    public boolean equals(Object obj) {
        boolean flag = super.equals(obj);
        if (flag == false) {
            return false;
        }
        if (!(obj instanceof TreeNode)) {
            return false;
        }
        TreeNode node = (TreeNode) obj;
        return this.children.equals(node.children);
    }
}
